/*
 * Copyright 2012-2014 glodon paas All right reserved. This software is the
 * confidential and proprietary information of glodon paas ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with glodon paas.
 */
package com.glodon.paas.monitor.web.controller;

import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_CACULATIONBEGIN_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_CACULATIONEND_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_DOWNLOADBEGIN_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_DOWNLOADEND_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_UPLOADBEGIN_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_UPLOADEND_TIME;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;

import com.glodon.paas.job.exception.JsonException;
import com.glodon.paas.job.model.TaskStatus;
import com.glodon.paas.job.util.DateFormatUtil;
import com.glodon.paas.job.util.JsonUtil;
import com.glodon.paas.monitor.server.biz.domain.TaskEntity;
import com.glodon.paas.monitor.server.dto.MonitorQueryDTO;
import com.glodon.paas.monitor.web.bean.ModelStatisticsBean;
import com.glodon.paas.util.DateUtil;

/**
 * @author licx 2013-2-1 下午4:59:10
 */
public class BaseController {

	protected static String											lastWeek;

	protected static ConcurrentHashMap<String, Map<String, String>>	cacheJobStatisticsMap	= new ConcurrentHashMap<String, Map<String, String>>();

	protected static ConcurrentHashMap<String, Map<String, String>>	cacheTaskStatisticsMap	= new ConcurrentHashMap<String, Map<String, String>>();

	public BaseController() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_YEAR, -7);
		Date dateTime = cal.getTime();
		lastWeek = DateUtil.formatDate(dateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
	}

	protected static MonitorQueryDTO buildMonitorQueryDTO(boolean needPage, String id, int fromNum, int pageNum,
			String fileName, String from, String to, String typeChoose) {

		MonitorQueryDTO taskQueryDTO = new MonitorQueryDTO();
		taskQueryDTO.setNeedPage(needPage);
		if (StringUtils.isNotBlank(from)) {
			from = from + " 00:00:00";
			Date fromDate = DateUtil.getDate(from, DateUtil.DAFAULT_DATETIME_FORMAT);
			from = DateUtil.formatDate(fromDate, DateUtil.DAFAULT_DATETIME_FORMAT);
			taskQueryDTO.setFromDate(from);
		}
		if (StringUtils.isNotBlank(to)) {
			to = to + " 23:59:59";
			Date toDate = DateUtil.getDate(to, DateUtil.DAFAULT_DATETIME_FORMAT);
			to = DateUtil.formatDate(toDate, DateUtil.DAFAULT_DATETIME_FORMAT);
			taskQueryDTO.setToDate(to);
		}

		if (StringUtils.isNotBlank(fileName)) {
			taskQueryDTO.setFileName(fileName);
		}
		if (StringUtils.isNotBlank(id)) {
			taskQueryDTO.setId(id);
		}
		if (StringUtils.isNotBlank(typeChoose)) {
			taskQueryDTO.setType(typeChoose);
		}

		taskQueryDTO.setFromNum(fromNum);
		taskQueryDTO.setPageNum(pageNum);

		return taskQueryDTO;
	}

	@SuppressWarnings("rawtypes")
	protected static void buildTaskMap(TaskEntity entity, Map<String, String> taskMap) throws JsonException,
			UnsupportedEncodingException {
		taskMap.put("taskId", entity.getId());
		taskMap.put("taskType", entity.getTaskType() == null ? "" : entity.getTaskType());
		Map taskInfoMap = new HashMap();
		try {
			taskInfoMap = JsonUtil
					.jsonToMap(String.valueOf(entity.getTaskInfo() == null ? "{}" : entity.getTaskInfo()));
		} catch (JsonException e) {
			throw new JsonException("Can not convert json to map.", e);
		}
		taskMap.put("jobId", taskInfoMap.get("jobId") == null ? "" : String.valueOf(taskInfoMap.get("jobId")));
		taskMap.put("agentIp", taskInfoMap.get("agent") == null ? "" : String.valueOf(taskInfoMap.get("agent")));
		taskMap.put(
				"originFilename",
				taskInfoMap.get("originFilename") == null ? "" : URLDecoder.decode(
						String.valueOf(taskInfoMap.get("originFilename")), "UTF-8"));
		String taskStatus = entity.getStatus() == null ? "" : entity.getStatus();
		String tires = null;
		if (taskInfoMap.get("stories") != null) {
			tires = taskInfoMap.get("stories").toString().replaceAll(",", "|");
		}

		String inQuqueTime = "";
		Date startTime = entity.getCreateTime();
		if (startTime != null) {
			inQuqueTime = DateFormatUtil.format(startTime);
		}

		String jobServerSumbitTime = "";
		if (entity.getJobServerSumbitTime() != null) {
			jobServerSumbitTime = DateFormatUtil.format(entity.getJobServerSumbitTime());
		}

		String downLoadTime = (String) taskInfoMap.get(PROPERTY_TASK_DOWNLOADBEGIN_TIME);
		Date downLoadDateTime = null;
		if (StringUtils.isNotBlank(downLoadTime)) {
			downLoadDateTime = DateUtil.getDate(downLoadTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			downLoadTime = DateUtil.formatDate(downLoadDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		String downLoadEndTime = (String) taskInfoMap.get(PROPERTY_TASK_DOWNLOADEND_TIME);
		Date downLoadEndDateTime = null;
		if (StringUtils.isNotBlank(downLoadEndTime)) {
			downLoadEndDateTime = DateUtil.getDate(downLoadEndTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			downLoadEndTime = DateUtil.formatDate(downLoadEndDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		long downLoadDuration = 0l;
		if (null != downLoadDateTime && null != downLoadEndDateTime) {
			downLoadDuration = downLoadEndDateTime.getTime() - downLoadDateTime.getTime();
		}

		String computeTime = (String) taskInfoMap.get(PROPERTY_TASK_CACULATIONBEGIN_TIME);
		Date computeDateTime = null;
		if (StringUtils.isNotBlank(computeTime)) {
			computeDateTime = DateUtil.getDate(computeTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			computeTime = DateUtil.formatDate(computeDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		String computeEndTime = (String) taskInfoMap.get(PROPERTY_TASK_CACULATIONEND_TIME);
		Date computeEndDateTime = null;
		if (StringUtils.isNotBlank(computeEndTime)) {
			computeEndDateTime = DateUtil.getDate(computeEndTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			computeEndTime = DateUtil.formatDate(computeEndDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}

		long computeDuration = 0l;
		if (TaskStatus.success.toString().equals(taskStatus) || TaskStatus.failure.toString().equals(taskStatus)) {
			if (null != computeDateTime && null != computeEndDateTime) {
				computeDuration = computeEndDateTime.getTime() - computeDateTime.getTime();
			}
		} else {
			if (null != computeDateTime) {
				computeDuration = System.currentTimeMillis() - computeDateTime.getTime();
			}
		}

		String uploadTime = (String) taskInfoMap.get(PROPERTY_TASK_UPLOADBEGIN_TIME);
		Date uploadDateTime = null;
		if (StringUtils.isNotBlank(uploadTime)) {
			uploadDateTime = DateUtil.getDate(uploadTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			uploadTime = DateUtil.formatDate(uploadDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		String upLoadEndTime = (String) taskInfoMap.get(PROPERTY_TASK_UPLOADEND_TIME);
		Date uploadEndDateTime = null;
		if (StringUtils.isNotBlank(upLoadEndTime)) {
			uploadEndDateTime = DateUtil.getDate(upLoadEndTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			upLoadEndTime = DateUtil.formatDate(uploadEndDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		long uploadDuration = 0l;
		if (null != uploadDateTime && null != uploadEndDateTime) {
			uploadDuration = uploadEndDateTime.getTime() - uploadDateTime.getTime();
		}

		String endTime = null;
		Date endTimeForDate = entity.getEndTime();
		if (null != endTimeForDate) {
			endTime = DateUtil.formatDate(endTimeForDate, DateUtil.DAFAULT_DATETIME_FORMAT);
		}

		long waitDuration = 0l;
		if (TaskStatus.running.toString().equals(taskStatus) || TaskStatus.success.toString().equals(taskStatus)
				|| TaskStatus.failure.toString().equals(taskStatus)) {
			if (null != computeDateTime && null != startTime) {
				waitDuration = computeDateTime.getTime() - startTime.getTime();
			}
		} else {
			if (null != startTime) {
				waitDuration = System.currentTimeMillis() - startTime.getTime();
			}
		}
		taskMap.put("taskStatus", taskStatus);
		taskMap.put("modelStatus", taskStatus);
		taskMap.put("countTires", tires == null ? "" : tires.toString());
		taskMap.put("inQuqueTime", inQuqueTime);
		taskMap.put("jobServerSumbitTime", jobServerSumbitTime);
		taskMap.put("downLoadTime", downLoadTime == null ? "" : downLoadTime);
		taskMap.put("downLoadDuration", String.valueOf(downLoadDuration));
		taskMap.put("computeTime", computeTime == null ? "" : computeTime);
		taskMap.put("computeDuration", String.valueOf(computeDuration));
		taskMap.put("uploadTime", uploadTime == null ? "" : uploadTime);
		taskMap.put("uploadDuration", String.valueOf(uploadDuration));
		taskMap.put("endTime", endTime);
		taskMap.put("waitDuration", String.valueOf(waitDuration));
		taskMap.put("errorMsg", taskInfoMap.get("errorMsg") == null ? "" : String.valueOf(taskInfoMap.get("errorMsg")));
	}

	protected static Map<String, List<Map<String, String>>> buildGroupByTaskTypeMap(List<Map<String, String>> mapList) {
		Map<String, List<Map<String, String>>> groupByTaskTypeMap = new HashMap<String, List<Map<String, String>>>();
		if (null != mapList && !mapList.isEmpty()) {
			for (Map<String, String> map : mapList) {
				String taskType = (String) map.get("taskType");
				if (taskType.indexOf("gcl") != -1) {
					taskType = "gcl";
				}
				if (null == groupByTaskTypeMap.get(taskType)) {
					List<Map<String, String>> groupByTaskTypeList = new ArrayList<Map<String, String>>();
					groupByTaskTypeList.add(map);
					groupByTaskTypeMap.put(taskType, groupByTaskTypeList);
				} else {
					List<Map<String, String>> groupByTaskTypeList = groupByTaskTypeMap.get(taskType);
					groupByTaskTypeList.add(map);
					groupByTaskTypeMap.remove(taskType);
					groupByTaskTypeMap.put(taskType, groupByTaskTypeList);
				}
			}
		}
		return groupByTaskTypeMap;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected static List<ModelStatisticsBean> buildModelStatisticsList(NumberFormat nf,
			Map<String, List<Map<String, String>>> groupByModelTypeMap, List<Map<String, String>> modelStatisticsListMap)
			throws Exception {
		List<ModelStatisticsBean> modelStatisticsList = new ArrayList<ModelStatisticsBean>(groupByModelTypeMap.size());
		for (Map.Entry<String, List<Map<String, String>>> entry : groupByModelTypeMap.entrySet()) {
			List<Map<String, String>> modelTypeList = entry.getValue();
			ModelStatisticsBean modelStatisticsDTO = new ModelStatisticsBean();
			modelStatisticsDTO.setTaskType(entry.getKey());
			long[] waitDurationArray = new long[modelTypeList.size()];
			long waitDurationSum = 0;
			long[] computeDurationArray = new long[modelTypeList.size()];
			long computeDurationSum = 0;
			int i = 0;
			for (Map<String, String> map : modelTypeList) {
				String modelStatus = (String) map.get("modelStatus");
				String waitDuration = (String) map.get("waitDuration");
				String computeDuration = (String) map.get("computeDuration");
				if (TaskStatus.created.toString().equals(modelStatus)
						|| TaskStatus.running.toString().equals(modelStatus)) {// 当前未完成的任务总数量
					modelStatisticsDTO.setNotFinishTaskNum(modelStatisticsDTO.getNotFinishTaskNum() + 1);
				}
				if (TaskStatus.created.toString().equals(modelStatus)) {// 等待任务数量
					modelStatisticsDTO.setWaitTaskNum(modelStatisticsDTO.getWaitTaskNum() + 1);
				}
				if (TaskStatus.running.toString().equals(modelStatus)) {// 正在处理任务数量
					modelStatisticsDTO.setRunningTaskNum(modelStatisticsDTO.getRunningTaskNum() + 1);
				}
				if (TaskStatus.success.toString().equals(modelStatus)
						|| TaskStatus.failure.toString().equals(modelStatus)
						|| TaskStatus.canceled.toString().equals(modelStatus)) {// 完成的任务数量
					modelStatisticsDTO.setFinishTaskNum(modelStatisticsDTO.getFinishTaskNum() + 1);
				}
				if (TaskStatus.success.toString().equals(modelStatus)) {// 成功的任务数量
					modelStatisticsDTO.setSuccessTaskNum(modelStatisticsDTO.getSuccessTaskNum() + 1);
				}
				if (TaskStatus.failure.toString().equals(modelStatus)) {// 失败的任务数量
					modelStatisticsDTO.setFailureTaskNum(modelStatisticsDTO.getFailureTaskNum() + 1);
				}
				waitDurationArray[i] = Long.valueOf(waitDuration);
				waitDurationSum = waitDurationSum + waitDurationArray[i];

				computeDurationArray[i] = Long.valueOf(computeDuration);
				computeDurationSum = computeDurationSum + computeDurationArray[i];

				i++;
			}

			if (null != modelTypeList && !modelTypeList.isEmpty()) {
				modelStatisticsDTO.setSumTaskNum(modelTypeList.size());
				double sumTaskNum = (double) modelStatisticsDTO.getSumTaskNum();
				modelStatisticsDTO.setWaitRate(nf.format((double) modelStatisticsDTO.getWaitTaskNum() / sumTaskNum));// 等待率(等待任务数量/总任务数量)
				modelStatisticsDTO.setRunningRate(nf.format((double) modelStatisticsDTO.getRunningTaskNum()
						/ sumTaskNum));// 处理率=正在处理任务数量/总任务数量
				modelStatisticsDTO
						.setFinishRate(nf.format((double) modelStatisticsDTO.getFinishTaskNum() / sumTaskNum));// 完成率=完成的任务数量/总任务数量
				modelStatisticsDTO.setSuccessRate(nf.format((double) modelStatisticsDTO.getSuccessTaskNum()
						/ sumTaskNum));// 成功率=成功的任务数量/总任务数量
				modelStatisticsDTO.setFailureRate(nf.format((double) modelStatisticsDTO.getFailureTaskNum()
						/ sumTaskNum));// 失败率=失败的任务数量/总任务数量

				Arrays.sort(waitDurationArray);
				modelStatisticsDTO.setMinWaitDuration(waitDurationArray[0]);// 最小等待时间
				modelStatisticsDTO.setMaxWaitDuration(waitDurationArray[modelTypeList.size() - 1]);// 最大等待时间
				modelStatisticsDTO.setAvgWaitDuration(waitDurationSum / modelTypeList.size());// 平均等待时间

				Arrays.sort(computeDurationArray);
				modelStatisticsDTO.setMinComputeDuration(computeDurationArray[0]);// 最小处理时间
				modelStatisticsDTO.setMaxComputeDuration(computeDurationArray[modelTypeList.size() - 1]);// 最大处理时间
				modelStatisticsDTO.setAvgComputeDuration(computeDurationSum / modelTypeList.size());// 平均处理时间
			}
			modelStatisticsList.add(modelStatisticsDTO);
			Map descMap = BeanUtils.describe(modelStatisticsDTO);
			cacheJobStatisticsMap.put(modelStatisticsDTO.getTaskType(), descMap);
			cacheTaskStatisticsMap.put(modelStatisticsDTO.getTaskType(), descMap);
			modelStatisticsListMap.add(descMap);
		}
		return modelStatisticsList;
	}

	protected static ModelStatisticsBean buildModelStatisticsSum(NumberFormat nf,
			List<ModelStatisticsBean> modelStatisticsList) {
		ModelStatisticsBean modelStatisticsSumDTO = null;
		if (null != modelStatisticsList && !modelStatisticsList.isEmpty()) {
			modelStatisticsSumDTO = new ModelStatisticsBean();
			for (ModelStatisticsBean modelStatisticsDTO : modelStatisticsList) {
				modelStatisticsSumDTO.setSumTaskNum(modelStatisticsSumDTO.getSumTaskNum()
						+ modelStatisticsDTO.getSumTaskNum());
				modelStatisticsSumDTO.setNotFinishTaskNum(modelStatisticsSumDTO.getNotFinishTaskNum()
						+ modelStatisticsDTO.getNotFinishTaskNum());
				modelStatisticsSumDTO.setWaitTaskNum(modelStatisticsSumDTO.getWaitTaskNum()
						+ modelStatisticsDTO.getWaitTaskNum());
				modelStatisticsSumDTO.setRunningTaskNum(modelStatisticsSumDTO.getRunningTaskNum()
						+ modelStatisticsDTO.getRunningTaskNum());
				modelStatisticsSumDTO.setFinishTaskNum(modelStatisticsSumDTO.getFinishTaskNum()
						+ modelStatisticsDTO.getFinishTaskNum());
				modelStatisticsSumDTO.setSuccessTaskNum(modelStatisticsSumDTO.getSuccessTaskNum()
						+ modelStatisticsDTO.getSuccessTaskNum());
				modelStatisticsSumDTO.setFailureTaskNum(modelStatisticsSumDTO.getFailureTaskNum()
						+ modelStatisticsDTO.getFailureTaskNum());
				modelStatisticsSumDTO.setMinWaitDuration(modelStatisticsSumDTO.getMinWaitDuration()
						+ modelStatisticsDTO.getMinWaitDuration());
				modelStatisticsSumDTO.setMaxWaitDuration(modelStatisticsSumDTO.getMaxWaitDuration()
						+ modelStatisticsDTO.getMaxWaitDuration());
				modelStatisticsSumDTO.setAvgWaitDuration(modelStatisticsSumDTO.getAvgWaitDuration()
						+ modelStatisticsDTO.getAvgWaitDuration());
				modelStatisticsSumDTO.setMinComputeDuration(modelStatisticsSumDTO.getMinComputeDuration()
						+ modelStatisticsDTO.getMinComputeDuration());
				modelStatisticsSumDTO.setMaxComputeDuration(modelStatisticsSumDTO.getMaxComputeDuration()
						+ modelStatisticsDTO.getMaxComputeDuration());
				modelStatisticsSumDTO.setAvgComputeDuration(modelStatisticsSumDTO.getAvgComputeDuration()
						+ modelStatisticsDTO.getAvgComputeDuration());

			}
			double sumTaskNum = (double) modelStatisticsSumDTO.getSumTaskNum();
			modelStatisticsSumDTO.setWaitRate(nf.format((double) modelStatisticsSumDTO.getWaitTaskNum() / sumTaskNum));
			modelStatisticsSumDTO.setRunningRate(nf.format((double) modelStatisticsSumDTO.getRunningTaskNum()
					/ sumTaskNum));
			modelStatisticsSumDTO.setFinishRate(nf.format((double) modelStatisticsSumDTO.getFinishTaskNum()
					/ sumTaskNum));
			modelStatisticsSumDTO.setSuccessRate(nf.format((double) modelStatisticsSumDTO.getSuccessTaskNum()
					/ sumTaskNum));
			modelStatisticsSumDTO.setFailureRate(nf.format((double) modelStatisticsSumDTO.getFailureTaskNum()
					/ sumTaskNum));
		}
		return modelStatisticsSumDTO;
	}
}
